package utility;
import java.io.BufferedInputStream;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.FileInputStream;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.InputStream;
import java.security.MessageDigest;

/**
 * @author sgugel
 * Utility Class for getting MD5-Checksums of files
 * This is used to protect the files the program saves
 */
public final class MD5Checksum {
	
	/**
	 * private constructor for utility classes.
	 */
	private MD5Checksum() {
		
	}
	/**
	 * @param fileName input file name
	 * @return md5-checksum of the input file as byte[]
	 * @throws Exception may throw io-exceptions
	 */
	public static byte[] newChecksum(final String fileName) 
			throws Exception {
		InputStream input = new FileInputStream(fileName);
		BufferedInputStream bInput = new BufferedInputStream(input);
		MessageDigest message = MessageDigest.getInstance("MD5");
		byte[] buffer = new byte[1024];
		int byteCount;
		do {
			byteCount = bInput.read(buffer);
			if (byteCount > 0) {
				message.update(buffer, 0, byteCount);
			}
		} while (byteCount != -1);
		bInput.close();
		input.close();
		return message.digest();
	}
	
	/**
	 * @param fileName input filename
	 * @return the md5-checksum of the input file, converted to a hex-string
	 * @throws Exception may throw io-exceptions
	 */
	public static String getMD5Checksum(final String fileName)
			throws Exception {
		byte[] checksum = newChecksum(fileName);
		String result = "";
	       for (int i = 0; i < checksum.length; i++) {
	           result += Integer.toString((checksum[i] & 0xff) + 0x100, 16).substring(1);
	       }
	       return result;
	}
	
	/**
	 * @param inputFileName input filename 
	 * @param outputFileName the md5-checksum of inputFileName will be written in this file
	 * @throws Exception may throw io-exceptions
	 */
	public static void saveChecksum(final String inputFileName, final String outputFileName)
			throws Exception {
		BufferedWriter out = new BufferedWriter(new FileWriter(outputFileName));
		out.write(getMD5Checksum(inputFileName));
		out.close();
	}
	
	/**
	 * @param fileName fileName of the file to test
	 * @param checksumFileName fileName of a file containing a checksum in the first line
	 * @return are the checksums equal?
	 */
	public static boolean verifyChecksum(final String fileName, final String checksumFileName) {
		BufferedReader bReader;
		boolean result = false;
		try {
		bReader =  new BufferedReader(new FileReader(checksumFileName));
		String chk1 = getMD5Checksum(fileName);
		String chk2 = bReader.readLine();
		bReader.close();
		result = chk1.equalsIgnoreCase(chk2);
		} catch (Exception e) {
			result = false;
		}
		return result;
	}
}
